package com.example.demo.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Aspect// 当前类是一个切面
@Component
public class UserAspect {
    /**
     * 定义pointcut的前置通知
     * 在执行目标方法之前执行的方法叫做前置通知
     */
    @Before("pointcut()")
    public void doBefore(){
        System.out.println("前置方法被执行了");
    }

    /**
     * 定义pointcut的后置通知
     */
    @After("pointcut()")
    public void doAfter(){
        System.out.println("后置方法被执行了");
    }

    /**
     * 返回之后的通知
     */
    @AfterReturning("pointcut()")
    public void doAfterReturning(){
        System.out.println("doAfterReturning方法被执行了");
    }

    /**
     * 抛出异常之后的通知
     */
    @AfterThrowing("pointcut()")
    public void doAfterThrowing(){
        System.out.println("AfterThrowing方法被执行了");
    }

    /**
     * 定义pointcut的环绕通知
     */
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint){
        //spring中的时间统计对象
        StopWatch stopWatch = new StopWatch();
        Object ret = null;
//        System.out.println("环绕通知：前置方法");
        try {
            stopWatch.start();//统计方法的执行时间，开始计时了
            //执行目标方法，以及目标方法所对应的相应的通知
            ret = joinPoint.proceed();
            stopWatch.stop();//统计方法的执行时间，停止计时了
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
//        System.out.println("环绕通知：后置方法");
        System.out.println(joinPoint.getSignature().getDeclaringTypeName() + "." +
                joinPoint.getSignature().getName() + "执行花费的时间" +
                stopWatch.getLastTaskTimeMillis() + "ms");
        return ret;
    }



    //定义切点，设置拦截规则
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){

    }

}
